package com.anuo.app.study.studymultithread;


public class StudyMultithreadInterview {

    public static void main(String[] args) {
        StudyMultithreadShare();
    }

    /**
     * 研究多线程的变量共享
     * 参考: http://www.jianshu.com/p/17acc262e520
     * 判断下面程序的输出:
     * 答案:
     * main thread b=2000
     * b=1000
     * 或
     * main thread b=1000
     * b=1000
     * 知识点:
     * 1.如果synchronized 修饰实例方法,相当于对当前实例加锁, 如下面的m2方法会先执行, 无论m2方法执行多久(可以放大Thread.sleep()的值)
     * 都要等到m2方法执行完了, 释放实例锁了, m1 方法才能开始执行.具体规则如下:
     * 1.1 对某个对象加锁(常见的对某个代码片段加锁,回去锁住一个object对象)，进入同步代码块前 需要获得此对象的锁才能进入。
     * 1.2 直接修饰非静态方法(如下面的m2方法):相当于对当前实例加锁，进入同步代码前要获得当前实例的锁。
     * 1.3 直接作用于静态方法:相当于对当前类加锁，进入同步代码前要获得当前类的锁。
     * 2.thread实例.start() 这个开始执行线程的方法, 并不表示线程马上会执行, 这个取决于cpu的调度, cpu繁忙的话会待会才执行
     * 3.如果thread实例.start()后面是主线程代码, 那么一般会先执行主线程代码,因为 thread实例.start()的执行需要一些耽搁, 而主线程是马上执行
     */
    public static void StudyMultithreadShare() {
        TestSync2 tt = new TestSync2();//1
        Thread t = new Thread(tt);  //2 传入tt实例对象, 后面在start run m1方法时就用的此tt 实例来调用m1方法.
        t.start(); //3

        try {
            tt.m2(); //4
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("main thread b=" + tt.b); //5
    }


    public static class TestSync2 implements Runnable {
        int b = 100;

        synchronized void m1() throws InterruptedException {
            b = 1000;
            Thread.sleep(500);
            System.out.println("b=" + b);
        }

        synchronized void m2() throws InterruptedException {
            Thread.sleep(250);
            b = 2000;

        }


        @Override
        public void run() {
            try {
                m1();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

